/**
 *
 * */

import SKILL_MAP_POS from "./skill_map_pos_json";

export interface o1Point {
    x: number;
    y: number;
}

export interface shouShiItem {
    //ID
    id: string;
    //坐标数组
    pos: o1Point[];
    //名称
    name?: string;
    //动态游标
    i: number;
}

//匹配度
export interface matchIdItem {
    id: string;
    match: number;
}

export const CLICK_MIN_PIXEL: number = 20;

export default class shouShiDataBase {

    static getCalcSkillIdOfMap(poss: cc.Vec2[]): string {
        //
        console.log(this.getAllMap(),"this.getAllMap()")
        let matchArray: matchIdItem[] = [];
        for (let map of this.getAllMap()) {
            let match = this.analysisMapAndPossMatch(map, poss);
            matchArray.push({id: map.id, match});
        }
        //按匹配度排序
        matchArray.sort((left: matchIdItem, right: matchIdItem) => {
            return right.match - left.match;
        });
        console.log('排序后', matchArray);
        return matchArray[0].id;
    }

    static getAllMap() {
        if (this.allMap == null || this.allMap.length <= 0) {
            this.initMap();
        }
        return this.allMap;
    }

    static getMapOfId(id: string) {
        for (let map of this.getAllMap()) {
            if (map.id == id) {
                return map;
            }
        }
        return null;
    }

    /**
     * 此处可提前调用来初始化 如不提前初始化，请勿在内部直接调用 this.allMap, 而是调用 this.getAllMap()来访问 this.allMap;
     * */
    static initMap() {
        let count = 0;
        this.allMap = []
        for (let id in SKILL_MAP_POS) {
            //
            this.allMap.push({
                id,
                i: count++,
                name: '',
                pos: SKILL_MAP_POS[id]
            });
        }
    }

    private static allMap: shouShiItem[] = [];

    /**
     * 对齐点集
     * @param poss 源点集
     * @param length 对齐长度
     * @return 目标点集
     * */
    private static alignmentPointSet(poss: cc.Vec2[], length: number): o1Point[] {
        let rtPoints: o1Point[] = [];
        //
        let addPointCount = length - poss.length;
        let scalePoint = addPointCount / poss.length;
        //需要添加才能对齐
        if (addPointCount > 0) {
            let needAdd = 0;
            //最后一个不动
            for (let i = 0; i < poss.length - 1; i++) {
                let curPos = poss[i];
                let nextPos = poss[i + 1];
                //源坐标先放入
                rtPoints.push({x: curPos.x, y: curPos.y});
                //
                needAdd += scalePoint;
                //至少需要添加一个
                if (needAdd > 1) {
                    //取整数
                    let IntNeedAdd = Math.floor(needAdd);
                    //坐标差
                    let posLess: o1Point = {x: nextPos.x - curPos.x, y: nextPos.y - curPos.y};
                    //插入n个 就分n+1段
                    let splitNum = IntNeedAdd + 1;
                    let scaleNum = 1 / splitNum;
                    //每一段的坐标偏移
                    let posScaleAdd: o1Point = {x: posLess.x * scaleNum, y: posLess.y * scaleNum};
                    //
                    for (let i = 0; i < IntNeedAdd; i++) {
                        let x = posScaleAdd.x + posScaleAdd.x * i;
                        let y = posScaleAdd.y + posScaleAdd.y * i;
                        rtPoints.push({x: curPos.x + x, y: curPos.y + y});
                    }
                    //添加完成 去掉整数
                    needAdd -= IntNeedAdd;
                }
            }
        } else if (addPointCount < 0) {//减少
            let needLess = 0;
            const lessPointCount = -addPointCount;
            const lessScalePoint = lessPointCount / length;
            for (let i = 0; i < poss.length - lessScalePoint; i++) {
                const currPos = poss[i];
                needLess += lessScalePoint;
                rtPoints.push({x: currPos.x, y: currPos.y});
                while (needLess > 1) {
                    //跳过
                    i++;
                    //
                    needLess--;
                }
            }
            const lastPoint = poss[poss.length - 1];
            rtPoints.push({x: lastPoint.x, y: lastPoint.y});
        } else {//已经对齐了
            for (let pot of poss) {
                rtPoints.push({x: pot.x, y: pot.y});
            }
        }
        //
        return rtPoints;
    }

    private static isClick(poss: cc.Vec2[]) {
        let maxDistance = 0;
        let firstPos = poss[0];
        for (let pot of poss) {
            let distance = pot.sub(firstPos).mag();
            maxDistance = Math.max(distance, maxDistance);
        }
        return maxDistance <= CLICK_MIN_PIXEL;
    }

    /**
     * 分析镜像和坐标集的匹配度 [0,1]
     * @param map 映射镜像
     * @param poss 有序坐标集合
     * @return 匹配度百分比 0:完全不匹配 1:完全匹配 0.5:50%匹配
     * */
    private static analysisMapAndPossMatch(map: shouShiItem, poss: cc.Vec2[]): number {
        //
        let o1Poss = this.alignmentPointSet(poss, map.pos.length);
        //开始分析
        let currMatchCount = 0;
        let currMatchSum = 0;
        //
        for (let i = 0; i < o1Poss.length - 1 && i < map.pos.length - 1; i++) {
            const currSkillPos = map.pos[i];
            const currCommandPos = o1Poss[i];
            const nextSkillPos = map.pos[i + 1];
            const nextCommandPos = o1Poss[i + 1];
            let skillRelations = this.getTwoPointRelations(currSkillPos, nextSkillPos);
            let commandRelations = this.getTwoPointRelations(currCommandPos, nextCommandPos);
            // console.log(`${map.name}角度--------------------`);
            // console.log(`${map.name}镜像角度`, skillRelations, currSkillPos, nextSkillPos);
            // console.log(`${map.name}指令角度`, commandRelations, currCommandPos, nextCommandPos);
            let currMatch = this.getRelationsMatchNumber(skillRelations, commandRelations);
            // console.log(i, '匹配度', currMatch);
            currMatchSum += currMatch;
            currMatchCount++;
        }
        let averageMatch = currMatchSum / currMatchCount;
        // console.log('总匹配度', averageMatch);

        return averageMatch;
    }

    /**
     * 比较相对关系
     * @param relationsPot1 角度1
     * @param relationsPot2 角度2
     * */
    private static getRelationsMatchNumber(relationsPot1: number, relationsPot2: number): number {
        let absAngle = Math.abs(relationsPot2 - relationsPot1);
        if (absAngle > 180) absAngle = 360 - absAngle;
        let match = (180 - absAngle) / 180;
        return match;
    }

    /**
     * 获取两点相对关系 角度
     * @return 角度
     * */
    private static getTwoPointRelations(firstPot: o1Point, nextPot: o1Point): number {
        let lp = cc.v2(firstPot.x, firstPot.y);
        let rp = cc.v2(nextPot.x, nextPot.y);
        let pot = rp.sub(lp);
        pot = this.clearZero(pot);
        let potXY0 = cc.v2(Math.abs(pot.x), 0.00001);
        let radian = potXY0.signAngle(pot);
        // console.log('下角度', pot, radian);
        //
        return this.radianToAngle(radian);
    }

    private static clearZero(v2: cc.Vec2) {
        if (v2.x == 0) {
            v2.x = 0.001;
        }
        if (v2.y == 0) {
            v2.y = 0.001;
        }
        return v2;
    }

    //弧度转角度
    private static radianToAngle(radian: number): number {
        return radian * 180 / Math.PI;
    }

    //角度转弧度
    private static angleTorDian(angle: number): number {
        return angle * Math.PI / 180;
    }
}





















































